/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.handlers;

import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Namespace;

import com.cea.papyrus.diagram.sequence.sedi.edit.command.DecideInteractionBoundsCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.AddInteractionToDiagramCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.CreateGraphicalElementCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.CreateInteractionCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.command.diagram.SetBoundsHintCommand;
import com.cea.papyrus.diagram.sequence.sedi.model.util.ModelUtil;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Handles creation of Interactions.
 * <p>
 * This handler is used from DiagramLayoutPolicy.
 * </p>
 * 
 * @author frankd@ifi.uio.no
 */
public class InteractionCreationHandler implements CreationHandler {

    public final EditPolicy hostPolicy;

    public InteractionCreationHandler(final EditPolicy hostPolicy) {
        this.hostPolicy = hostPolicy;
    }

    public Command[] getCreateCommands(final CreateRequest request) {
        final GraphicalEditPart host = (GraphicalEditPart) hostPolicy.getHost();
        final Diagram diagram = (Diagram) host.getModel();

        // Preconditions:
        // Only one interaction is allowed in this kind of diagram.
        if (!(ModelUtil.getInteractions(diagram)).isEmpty())
            return null;

        // The following commands are created:
        // SetBoundsHintCommand [SeDi]
        // Registers a Bounds hint that can be used when the
        // SeDi GraphcialElement is created. (This command is created
        // direcly by the EditPolicy.)
        // CreateInteractionCommand [UML]
        // Creates the UML Interaction and adds it to the UML collaboration.
        // When the command is executed, a GraphicalElement will be
        // created in response to the notification. This creation will consume
        // the Bounds hint set previously.
        // AddInteractionToDiagramCommand [SeDi]
        // Diagrams only show explicitely added interactions, so the
        // new interaction must be added explicitely.

        final DecideInteractionBoundsCommand decideBoundsCmd = new DecideInteractionBoundsCommand();
        decideBoundsCmd.setAnyEditPart(host);

        final SetBoundsHintCommand hintCmd = new SetBoundsHintCommand();
        // glue: hint

        NamedElement element =
                (NamedElement) ((Uml1SemanticModelBridge) diagram.getOwner()).getElement();
        Namespace ownerNamespace = element.getNamespace();
        final Namespace namespace =
                element instanceof Namespace ? (Namespace) element : ownerNamespace;

        final CreateInteractionCommand createCmd = new CreateInteractionCommand();
        createCmd.setNamespace(namespace);

        final CreateGraphicalElementCommand createGECmd = new CreateGraphicalElementCommand();
        createGECmd.setParentGE(diagram);
        createGECmd.setAnyEditPart(host);

        final AddInteractionToDiagramCommand addCmd = new AddInteractionToDiagramCommand();
        addCmd.setDiagram(diagram);

        Command glue1 = new Command() {
            public void execute() {
                hintCmd.setHint(decideBoundsCmd.getPreferredBounds());
            }
        };

        Command glueGE = new Command() {
            /**
             * @see org.eclipse.gef.commands.Command#execute()
             */
            @Override
            public void execute() {
                createGECmd.setElement(createCmd.getInteraction());
            }
        };

        Command glue2 = new Command() {
            public void execute() {
                addCmd.setInteraction(createCmd.getInteraction());
            }
        };

        return new Command[] {
                decideBoundsCmd, glue1, hintCmd, createCmd, glueGE, createGECmd, glue2, addCmd
        };
    }
}
